Skip to content

Custom backend eni keewis#1

Closed
eni-awowale wants to merge 7 commits into
keewis:custom-backendfrom
eni-awowale:custom-backend-eni-keewis
Closed

Custom backend eni keewis#1
eni-awowale wants to merge 7 commits into
keewis:custom-backendfrom
eni-awowale:custom-backend-eni-keewis

Conversation

@eni-awowale

Copy link
Copy Markdown

Building off of @keewis branch!

I was thinking about actual science workflows for manipulating gifs and writing time series plot images as gifs came to mind.

Here is a quick little example:

ImageIOBackend().write_dataset_gif(xr.tutorial.open_dataset('precipitation.nc4', group='observed'), 'advanced/backends/img_data/precip.gif', 'precipitation', 'time', plot=True)

cc
@VeckoTheGecko and @ianhi

@keewis keewis left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel free to take over my branch (or merge the branch and create a separate PR on the main repo) if that makes the workflow easier

time_dim: str,
plot: bool = False,
plot_outpath: str ='plot_image',
):

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we usually call these to_*, so may be a good option? Otherwise save_dataset (for symmetry with open_dataset?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, good point!

Comment on lines +142 to +156
if plot:
img_count = len(dataset[time_dim])
jpg_names = []
variable_da = dataset[variable]
for i in range(img_count):
plt.figure()
variable_da[i].plot(
x="lon",
y="lat",
vmin=variable_da.min(),
vmax=variable_da.max())
jpg_name = f'img_data/{plot_outpath}_{i}.jpg'
plt.savefig(jpg_name)
jpg_names.append(jpg_name)
self.write_jpg_gif(jpg_names, out_filename)

@keewis keewis Jun 29, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue that this should be an accessor method instead. Completely changing behavior of a function based on a flag feels really weird to me

Edit: but maybe this is just a different way of writing the data? In which case I'd use a method="matplotlib" or method="imageio" parameter.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, i was thinking of it as more so a different way of writing the data since the source, an xr.Dataset, is the same. i like that method="matplotlib" is more explicit so i will go with that.

@eni-awowale

Copy link
Copy Markdown
Author

Closing for PR to upstream.

Comment on lines +154 to +156
plt.savefig(jpg_name)
jpg_names.append(jpg_name)
self.write_jpg_gif(jpg_names, out_filename)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could use animations instead of writing to image files, then aggregating into gif:

https://matplotlib.org/stable/users/explain/animations/animations.html#animation-writers

Comment on lines +159 to +169
frames_array = np.stack(
[dataset[variable][x] for x in range(len(dataset[time_dim]))], axis=0
)
iio.imwrite(
out_filename,
frames_array,
extension=".gif",
loop=0,
duration=100,
background=1,
)

@keewis keewis Jul 12, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that's about as far as you can get with gifs since the color palette is something it forces onto you. Local color tables should help quite a bit, but in the end you'll need a way to (and also invert that)

  1. normalize the data
  2. discretize (if you pass local_color_table to imwrite and provided "local" means "block-local" not "frame-local", it might be possible to skip this)
  3. look up colors

The last step should be pretty easy to invert (and the second can probably be skipped for block-local color tables), but for the first we need the normalization parameters, which may be tricky: pillow does not appear to support writing application extension blocks. As a workaround, we can create a {gif-path}.json (e.g. test.gif.json) to store the metadata (if it doesn't exist we skip the inversion of the normalization step).

The above would get us pretty close to what the matplotlib method is doing, which also follows the normalization + colormap lookup / interpolation steps (though there may be additional elements like axis ticks or labels).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants